package com.caregiver.watch.business.user.utils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.regex.Pattern;

/**
 * 身份证校验工具类
 * 支持18位身份证号码的格式、校验码、出生日期等验证
 */
public class IdCardUtils {

    /**
     * 18位身份证号码校验正则表达式
     */
    private static final Pattern ID_CARD_PATTERN = Pattern.compile(
            "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$"
    );

    /**
     * 省份代码数组
     */
    private static final String[] PROVINCE_CODES = {
            "11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36", "37",
            "41", "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65", "71", "81", "82", "91"
    };

    /**
     * 身份证校验码
     */
    private static final char[] CHECK_CODES = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};

    /**
     * 加权因子
     */
    private static final int[] WEIGHT_FACTORS = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};


    public static boolean isNoValidIdCard(String idCard) {
        return !isValidIdCard(idCard);
    }

    /**
     * 校验身份证号码是否合法
     *
     * @param idCard 身份证号码
     * @return 是否合法
     */
    public static boolean isValidIdCard(String idCard) {
        if (idCard == null || idCard.trim().isEmpty()) {
            return false;
        }

        idCard = idCard.trim().toUpperCase();

        // 1. 格式校验
        if (!ID_CARD_PATTERN.matcher(idCard).matches()) {
            return false;
        }

        // 2. 省份代码校验
        if (!isValidProvinceCode(idCard.substring(0, 2))) {
            return false;
        }

        // 3. 出生日期校验
        if (!isValidBirthDate(idCard.substring(6, 14))) {
            return false;
        }

        // 4. 校验码校验
        if (!isValidCheckCode(idCard)) {
            return false;
        }

        return true;
    }

    /**
     * 校验省份代码是否合法
     *
     * @param provinceCode 省份代码
     * @return 是否合法
     */
    private static boolean isValidProvinceCode(String provinceCode) {
        for (String code : PROVINCE_CODES) {
            if (code.equals(provinceCode)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 校验出生日期是否合法
     *
     * @param birthDateStr 出生日期字符串(yyyyMMdd格式)
     * @return 是否合法
     */
    private static boolean isValidBirthDate(String birthDateStr) {
        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            LocalDate birthDate = LocalDate.parse(birthDateStr, formatter);

            // 检查日期是否在合理范围内(1900年至今)
            LocalDate minDate = LocalDate.of(1900, 1, 1);
            LocalDate maxDate = LocalDate.now();

            return !birthDate.isBefore(minDate) && !birthDate.isAfter(maxDate);
        } catch (DateTimeParseException e) {
            return false;
        }
    }

    /**
     * 校验身份证校验码是否正确
     *
     * @param idCard 身份证号码
     * @return 校验码是否正确
     */
    private static boolean isValidCheckCode(String idCard) {
        // 计算前17位数字的加权和
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            char c = idCard.charAt(i);
            if (!Character.isDigit(c)) {
                return false;
            }
            sum += (c - '0') * WEIGHT_FACTORS[i];
        }

        // 计算校验码
        int remainder = sum % 11;
        char expectedCheckCode = CHECK_CODES[remainder];
        char actualCheckCode = idCard.charAt(17);

        return expectedCheckCode == actualCheckCode;
    }

    /**
     * 获取身份证中的出生日期
     *
     * @param idCard 身份证号码
     * @return 出生日期(yyyy - MM - dd格式)
     */
    public static String getBirthDate(String idCard) {
        if (!isValidIdCard(idCard)) {
            return null;
        }

        String birthDateStr = idCard.substring(6, 14);
        return birthDateStr.substring(0, 4) + "-" +
                birthDateStr.substring(4, 6) + "-" +
                birthDateStr.substring(6, 8);
    }

    /**
     * 获取身份证中的性别
     *
     * @param idCard 身份证号码
     * @return 性别(0 - 女, 1 - 男)
     */
    public static Integer getGender(String idCard) {
        if (!isValidIdCard(idCard)) {
            return null;
        }

        // 第17位数字奇数为男，偶数为女
        int genderDigit = idCard.charAt(16) - '0';
        return genderDigit % 2;
    }

    /**
     * 获取身份证中的年龄
     *
     * @param idCard 身份证号码
     * @return 年龄
     */
    public static Integer getAge(String idCard) {
        if (!isValidIdCard(idCard)) {
            return null;
        }

        String birthDateStr = getBirthDate(idCard);
        if (birthDateStr == null) {
            return null;
        }

        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate birthDate = LocalDate.parse(birthDateStr, formatter);
            LocalDate currentDate = LocalDate.now();

            return java.time.Period.between(birthDate, currentDate).getYears();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取身份证中的省份代码
     *
     * @param idCard 身份证号码
     * @return 省份代码
     */
    public static String getProvinceCode(String idCard) {
        if (!isValidIdCard(idCard)) {
            return null;
        }
        return idCard.substring(0, 2);
    }

    /**
     * 脱敏身份证号码
     *
     * @param idCard 身份证号码
     * @return 脱敏后的身份证号码
     */
    public static String maskIdCard(String idCard) {
        if (idCard == null || idCard.length() < 18) {
            return idCard;
        }

        return idCard.substring(0, 6) + "********" + idCard.substring(14);
    }

    /**
     * 校验并获取身份证信息
     *
     * @param idCard 身份证号码
     * @return 身份证信息对象
     */
    public static IdCardInfo validateAndGetInfo(String idCard) {
        if (!isValidIdCard(idCard)) {
            return null;
        }

        IdCardInfo info = new IdCardInfo();
        info.setIdCard(idCard);
        info.setBirthDate(getBirthDate(idCard));
        info.setGender(getGender(idCard));
        info.setAge(getAge(idCard));
        info.setProvinceCode(getProvinceCode(idCard));
        info.setValid(true);

        return info;
    }

    /**
     * 身份证信息类
     */
    public static class IdCardInfo {
        private String idCard;
        private String birthDate;
        private Integer gender; // 0-女, 1-男
        private Integer age;
        private String provinceCode;
        private boolean valid;

        // Getters and Setters
        public String getIdCard() {
            return idCard;
        }

        public void setIdCard(String idCard) {
            this.idCard = idCard;
        }

        public String getBirthDate() {
            return birthDate;
        }

        public void setBirthDate(String birthDate) {
            this.birthDate = birthDate;
        }

        public Integer getGender() {
            return gender;
        }

        public void setGender(Integer gender) {
            this.gender = gender;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }

        public String getProvinceCode() {
            return provinceCode;
        }

        public void setProvinceCode(String provinceCode) {
            this.provinceCode = provinceCode;
        }

        public boolean isValid() {
            return valid;
        }

        public void setValid(boolean valid) {
            this.valid = valid;
        }

        @Override
        public String toString() {
            return "IdCardInfo{" +
                    "idCard='" + maskIdCard(idCard) + '\'' +
                    ", birthDate='" + birthDate + '\'' +
                    ", gender=" + (gender == 0 ? "女" : "男") +
                    ", age=" + age +
                    ", provinceCode='" + provinceCode + '\'' +
                    ", valid=" + valid +
                    '}';
        }
    }
}
